package hku.cs.lunuo.profile;

import hku.cs.lunuo.instrument.CoverageInstrument;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.XMLOutputter;

import soot.PackManager;
import soot.Transform;
import soot.options.Options;

public class Coverage {
	public static HashMap<String, HashMap<String, HashMap<Integer, ArrayList<Set<Integer>>>>> coverage = 
		new HashMap<String, HashMap<String, HashMap<Integer, ArrayList<Set<Integer>>>>>();
	public static void main(String[] args) {
		Options.v().set_keep_line_number(true);
		
		Options.v().set_time(false);
		PackManager.v().getPack("jap").add(
				new Transform("jap.instrumenter", CoverageInstrument.v()));
		Options.v().setPhaseOption("gb.a1", "enabled:false");
		Options.v().setPhaseOption("gb.cf", "enabled:false");
		Options.v().setPhaseOption("gb.a2", "enabled:false");
		Options.v().setPhaseOption("gb.ule", "enabled:false");
		Options.v().setPhaseOption("gop", "enabled:false");
		Options.v().setPhaseOption("bb.lso", "enabled:false");
		Options.v().setPhaseOption("bb.pho", "enabled:false");
		Options.v().setPhaseOption("bb.ule", "enabled:false");
		Options.v().setPhaseOption("bb.lp", "enabled:false");
		Options.v().set_no_output_inner_classes_attribute(true);
//		Options.v().set_src_prec(Options.src_prec_java);
		soot.Main.main(args);
		toXML(args[1]);	
		System.out.println("Over --------- ");
	}
	
	public static void toXML(String outputDir){
		for(String className : Coverage.coverage.keySet()){
			Element xmlRoot = new Element("class");
			xmlRoot.setAttribute("name", className);
			Document xmlDoc = new Document(xmlRoot);
			HashMap<String, HashMap<Integer, ArrayList<Set<Integer>>>> inHelp = Coverage.coverage.get(className);
			for(String methodName : inHelp.keySet()){
				Element xmlMethod = new Element("method");
				xmlMethod.setAttribute("name", methodName);
				HashMap<Integer, ArrayList<Set<Integer>>> inInHelp = inHelp.get(methodName);
				for (Integer i : inInHelp.keySet()) {
					Element xmlBlock = new Element("block");
					xmlBlock.setAttribute("index", i.toString());
					ArrayList<Set<Integer>> aList = inInHelp.get(i);
					
					Set<Integer> preSet = aList.get(0);
					Iterator<Integer> preSetIt = preSet.iterator();
					String preStr = "";
					while(preSetIt.hasNext()){
						preStr+=preSetIt.next()+",";
					}
					Element xmlPre = new Element("preBlocks");
					xmlPre.addContent(preStr);
					xmlBlock.addContent(xmlPre);
					
					Set<Integer> succSet = aList.get(1);
					Iterator<Integer> succSetIt = succSet.iterator();
					String succStr = "";
					while(succSetIt.hasNext()){
						succStr+=succSetIt.next()+",";
					}
					Element xmlSucc = new Element("succBlocks");
					xmlSucc.addContent(succStr);
					xmlBlock.addContent(xmlSucc);
					
					Set<Integer> unitSet = aList.get(2);
					Iterator<Integer> unitSetIt = unitSet.iterator();
					String unitStr ="";
					while(unitSetIt.hasNext()){
						unitStr+=unitSetIt.next()+",";
					}
					Element xmlStatement = new Element("statement");
					xmlStatement.addContent(unitStr);
					xmlBlock.addContent(xmlStatement);
					
					xmlMethod.addContent(xmlBlock);
				}
				xmlRoot.addContent(xmlMethod);
			}
			try {
				new File(outputDir+"/cfg").mkdir();
				new XMLOutputter().output(xmlDoc, new FileOutputStream(new File(
						outputDir+"/cfg", className + ".xml")));
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

}
